package com.nineclock.auth.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.nineclock.auth.entity.IntegrationAuthenticationEntity;
import com.nineclock.auth.processor.AuthenticationProcessor;
import com.nineclock.auth.threadlocal.IntegrationAuthenticationHolder;
import com.nineclock.auth.threadlocal.UserHolder;
import com.nineclock.common.entity.UserInfo;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.system.dto.SysCompanyUserDTO;
import com.nineclock.system.dto.SysRoleDTO;
import com.nineclock.system.dto.SysUserDTO;
import com.nineclock.system.feign.SysUserFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

@Component
public class UserDetailsServiceImpl implements UserDetailsService {
    //自动装配 两种认证处理器对象
    @Autowired
    List<AuthenticationProcessor> processors;


    @Autowired
    SysUserFeign userFeign;
    /**
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //从当前线程中获取  认证的实体对象
        IntegrationAuthenticationEntity entity = IntegrationAuthenticationHolder.get();
        //获取 我们要使用的 认证处理器对象
        AuthenticationProcessor processor = this.chooseAuthenticationProcessor(entity);

        //获取SysUser系统用户对象
        SysUserDTO userDTO = processor.authenticate(entity);

        UserInfo userInfo = BeanHelper.copyProperties(userDTO, UserInfo.class);
        //获取 客户端id
        String client_id = entity.getAuthParameter("client_id");

        String companyId = entity.getAuthParameter("company_id");
        //pc 端:要求必须是管理员才能登录
        //第一次访问： 需要来判定是否是管理员, 条件只有 用户id, 查询相关的员工，且包括角色，判断是否是管理员
        //第二次访问： 是选择了企业， 参数多了一个企业id，  根据企业id和用户id 查询员工，判断是否是管理员
        if(entity != null && "pc_client".equals(client_id)){
            //如果企业id为null，说明是第一次 点击登录
            if(StrUtil.isEmpty(companyId)){
                List<SysCompanyUserDTO> companyUserDTOList = userFeign.queryCompanyUser(null, userDTO.getId()).getData();

                if(CollectionUtil.isEmpty(companyUserDTOList)){
                    throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
                }

                //判断是否是管理员
                if(!this.checkCompanyUserAdmin(companyUserDTOList)){
                    //如果不是管理员
                    throw new NcException(ResponseEnum.USER_NOT_COMPANY_ADMIN);
                }

                if(companyUserDTOList.size() == 1){
                    //重新封装 企业信息
                    wrapper(userInfo, companyUserDTOList.get(0));
                }

            }
            //否则说明是第二此点击，选择了企业
            else{
                List<SysCompanyUserDTO> companyUserDTOList = userFeign.queryCompanyUser(Long.valueOf(companyId), userDTO.getId()).getData();

                if(CollectionUtil.isEmpty(companyUserDTOList)){
                    throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
                }

                //判断是否是管理员
                if(!this.checkCompanyUserAdmin(companyUserDTOList)){
                    //如果不是管理员
                    throw new NcException(ResponseEnum.USER_NOT_COMPANY_ADMIN);
                }


                //重新封装 企业信息
                wrapper(userInfo, companyUserDTOList.get(0));
            }


        }else{
            //app 端: 只要是用户，且密码验证没问题就可以登录
            if(StrUtil.isEmpty(companyId)){
                companyId = userDTO.getLastLoginCompanyId() + "";
            }

            List<SysCompanyUserDTO> companyUserDTOS =
                    userFeign.queryCompanyUser(Long.valueOf(companyId), userDTO.getId()).getData();

            if(CollectionUtil.isNotEmpty(companyUserDTOS)){
                wrapper(userInfo, companyUserDTOS.get(0));
            }
        }






        //存储当前 线程
        UserHolder.set(userInfo);

        if(userDTO != null){
            GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_ADMIN");
            User user = new User(JSONUtil.toJsonStr(userInfo), userDTO.getPassword(), Arrays.asList(grantedAuthority));
            return user;
        }else{
            throw new NcException(ResponseEnum.INVALID_USERNAME_PASSWORD);
        }

//        return User.withUsername(username)
//                .password("$2a$10$yRkoWX3dbPF8TX4KhB9kC.C4XiOJ4ThD/YQoersDtZjzJUYp4Rs7a")
//                .authorities("ROLE_ADMIN","P1").build();
    }

    /**
     * 判断 我们需要使用哪种处理方案
     * @param entity
     * @return
     */
    public AuthenticationProcessor chooseAuthenticationProcessor(IntegrationAuthenticationEntity entity){
        if(processors != null){
            for (AuthenticationProcessor processor : processors) {
                boolean flag = processor.support(entity);
                if(flag){
                    return processor;
                }
            }
        }

        return null;
    }


    /**
     * 检查员工是否是管理员
     * @return
     */
    public Boolean checkCompanyUserAdmin(List<SysCompanyUserDTO> companyUserDTOList){
        //只要有个员工是管理员，即可返回true
        for (SysCompanyUserDTO companyUserDTO : companyUserDTOList) {
            List<SysRoleDTO> roles = companyUserDTO.getRoles();
            if(CollectionUtil.isNotEmpty(roles)){
                for (SysRoleDTO role : roles) {
                    if(role.getRoleName().startsWith("ROLE_ADMIN_")){
                        return true;
                    }
                }
            }
        }
        //如果循环完成，没有返回true，说明不是管理员
        return false;
    }


    public void wrapper(UserInfo userInfo, SysCompanyUserDTO companyUserDTO){
        userInfo.setCompanyId(companyUserDTO.getCompanyId()); //企业id
        userInfo.setCompanyUserId(companyUserDTO.getId()); // 企业员工id
        userInfo.setCompanyName(companyUserDTO.getCompanyName()); //企业名称
        userInfo.setWorkNumber(companyUserDTO.getWorkNumber()); //工号
        userInfo.setPost(companyUserDTO.getPost()); //职务
        userInfo.setDepartmentId(companyUserDTO.getDepartmentId()) ; //部门id
        userInfo.setDepartmentName(companyUserDTO.getDepartmentName()); // 部门名称
        userInfo.setEnable(true);
    }

}